package com.gzc.just.play.last.war.common.share.performance;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * Performance monitor
 * Collects system runtime performance metrics
 */
@Component
public class PerformanceMonitor {
    
    private static final Logger log = LoggerFactory.getLogger(PerformanceMonitor.class);
    
    // JVM底层接口
    private final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    private final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
    
    // 性能指标
    private final ConcurrentHashMap<String, LongAdder> counters = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, AtomicLong> gauges = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Timer> timers = new ConcurrentHashMap<>();
    
    /**
     * 增加计数器
     */
    public void incrementCounter(String name) {
        counters.computeIfAbsent(name, k -> new LongAdder()).increment();
    }
    
    /**
     * 增加计数器（指定值）
     */
    public void incrementCounter(String name, long value) {
        counters.computeIfAbsent(name, k -> new LongAdder()).add(value);
    }
    
    /**
     * 设置仪表值
     */
    public void setGauge(String name, long value) {
        gauges.put(name, new AtomicLong(value));
    }
    
    /**
     * 开始计时
     */
    public Timer startTimer(String name) {
        return timers.compute(name, (k, v) -> new Timer());
    }
    
    /**
     * 结束计时并记录
     */
    public void recordTime(String name, Timer timer) {
        if (timer != null) {
            timer.record();
            timers.remove(name);
        }
    }
    
    /**
     * 记录计时器
     */
    public void recordTimer(String name, long duration) {
        Timer timer = new Timer();
        timer.recordDuration(duration);
        timers.computeIfAbsent(name, k -> timer).aggregate(timer);
    }
    
    /**
     * 记录错误
     */
    public void recordError() {
        incrementCounter("errors");
    }
    
    /**
     * 获取计数器值
     */
    public long getCounter(String name) {
        LongAdder adder = counters.get(name);
        return adder != null ? adder.sum() : 0;
    }
    
    /**
     * 获取仪表值
     */
    public long getGauge(String name) {
        AtomicLong gauge = gauges.get(name);
        return gauge != null ? gauge.get() : 0;
    }
    
    /**
     * 获取系统指标
     */
    public SystemMetrics getSystemMetrics() {
        SystemMetrics metrics = new SystemMetrics();
        
        // 线程信息
        metrics.setThreadCount(threadMXBean.getThreadCount());
        metrics.setDaemonThreadCount(threadMXBean.getDaemonThreadCount());
        metrics.setPeakThreadCount(threadMXBean.getPeakThreadCount());
        
        // 内存信息
        MemoryUsage heapUsage = memoryMXBean.getHeapMemoryUsage();
        MemoryUsage nonHeapUsage = memoryMXBean.getNonHeapMemoryUsage();
        
        if (heapUsage != null) {
            metrics.setHeapUsed(heapUsage.getUsed());
            metrics.setHeapMax(heapUsage.getMax());
            metrics.setHeapCommitted(heapUsage.getCommitted());
        }
        
        if (nonHeapUsage != null) {
            metrics.setNonHeapUsed(nonHeapUsage.getUsed());
            metrics.setNonHeapMax(nonHeapUsage.getMax());
            metrics.setNonHeapCommitted(nonHeapUsage.getCommitted());
        }
        
        return metrics;
    }
    
    /**
     * 获取自定义指标
     */
    public CustomMetrics getCustomMetrics() {
        CustomMetrics metrics = new CustomMetrics();
        
        // 计数器
        ConcurrentHashMap<String, Long> counterValues = new ConcurrentHashMap<>();
        counters.forEach((name, adder) -> counterValues.put(name, adder.sum()));
        metrics.setCounters(counterValues);
        
        // 仪表
        metrics.setGauges(new ConcurrentHashMap<>(gauges));
        
        // 计时器
        ConcurrentHashMap<String, TimerStats> timerStats = new ConcurrentHashMap<>();
        timers.forEach((name, timer) -> {
            TimerStats stats = new TimerStats();
            stats.setCount(timer.getCount());
            stats.setAverageTime(timer.getAverageTime());
            stats.setMinTime(timer.getMinTime());
            stats.setMaxTime(timer.getMaxTime());
            timerStats.put(name, stats);
        });
        metrics.setTimers(timerStats);
        
        return metrics;
    }
    
    /**
     * 重置所有指标
     */
    public void reset() {
        counters.clear();
        gauges.clear();
        timers.clear();
        log.info("Performance metrics reset");
    }
    
    /**
     * 系统指标类
     */
    public static class SystemMetrics {
        private int threadCount;
        private int daemonThreadCount;
        private int peakThreadCount;
        private long heapUsed;
        private long heapMax;
        private long heapCommitted;
        private long nonHeapUsed;
        private long nonHeapMax;
        private long nonHeapCommitted;
        
        // Getters and setters
        public int getThreadCount() { return threadCount; }
        public void setThreadCount(int threadCount) { this.threadCount = threadCount; }
        
        public int getDaemonThreadCount() { return daemonThreadCount; }
        public void setDaemonThreadCount(int daemonThreadCount) { this.daemonThreadCount = daemonThreadCount; }
        
        public int getPeakThreadCount() { return peakThreadCount; }
        public void setPeakThreadCount(int peakThreadCount) { this.peakThreadCount = peakThreadCount; }
        
        public long getHeapUsed() { return heapUsed; }
        public void setHeapUsed(long heapUsed) { this.heapUsed = heapUsed; }
        
        public long getHeapMax() { return heapMax; }
        public void setHeapMax(long heapMax) { this.heapMax = heapMax; }
        
        public long getHeapCommitted() { return heapCommitted; }
        public void setHeapCommitted(long heapCommitted) { this.heapCommitted = heapCommitted; }
        
        public long getNonHeapUsed() { return nonHeapUsed; }
        public void setNonHeapUsed(long nonHeapUsed) { this.nonHeapUsed = nonHeapUsed; }
        
        public long getNonHeapMax() { return nonHeapMax; }
        public void setNonHeapMax(long nonHeapMax) { this.nonHeapMax = nonHeapMax; }
        
        public long getNonHeapCommitted() { return nonHeapCommitted; }
        public void setNonHeapCommitted(long nonHeapCommitted) { this.nonHeapCommitted = nonHeapCommitted; }
    }
    
    /**
     * 自定义指标类
     */
    public static class CustomMetrics {
        private ConcurrentHashMap<String, Long> counters;
        private ConcurrentHashMap<String, AtomicLong> gauges;
        private ConcurrentHashMap<String, TimerStats> timers;
        
        // Getters and setters
        public ConcurrentHashMap<String, Long> getCounters() { return counters; }
        public void setCounters(ConcurrentHashMap<String, Long> counters) { this.counters = counters; }
        
        public ConcurrentHashMap<String, AtomicLong> getGauges() { return gauges; }
        public void setGauges(ConcurrentHashMap<String, AtomicLong> gauges) { this.gauges = gauges; }
        
        public ConcurrentHashMap<String, TimerStats> getTimers() { return timers; }
        public void setTimers(ConcurrentHashMap<String, TimerStats> timers) { this.timers = timers; }
    }
    
    /**
     * 计时器统计类
     */
    public static class TimerStats {
        private long count;
        private double averageTime;
        private long minTime;
        private long maxTime;
        
        // Getters and setters
        public long getCount() { return count; }
        public void setCount(long count) { this.count = count; }
        
        public double getAverageTime() { return averageTime; }
        public void setAverageTime(double averageTime) { this.averageTime = averageTime; }
        
        public long getMinTime() { return minTime; }
        public void setMinTime(long minTime) { this.minTime = minTime; }
        
        public long getMaxTime() { return maxTime; }
        public void setMaxTime(long maxTime) { this.maxTime = maxTime; }
    }
    
    /**
     * 计时器类
     */
    public static class Timer {
        private final long startTime = System.nanoTime();
        private long minTime = Long.MAX_VALUE;
        private long maxTime = Long.MIN_VALUE;
        private long count = 0;
        private long totalTime = 0;
        
        public void record() {
            long duration = System.nanoTime() - startTime;
            
            // 更新统计
            if (duration < minTime) {
                minTime = duration;
            }
            if (duration > maxTime) {
                maxTime = duration;
            }
            count++;
            totalTime += duration;
        }
        
        public void recordDuration(long duration) {
            // 更新统计
            if (duration < minTime) {
                minTime = duration;
            }
            if (duration > maxTime) {
                maxTime = duration;
            }
            count++;
            totalTime += duration;
        }
        
        public void aggregate(Timer other) {
            if (other.minTime < minTime) {
                minTime = other.minTime;
            }
            if (other.maxTime > maxTime) {
                maxTime = other.maxTime;
            }
            count += other.count;
            totalTime += other.totalTime;
        }
        
        public long getCount() {
            return count;
        }
        
        public double getAverageTime() {
            return count > 0 ? (double) totalTime / count : 0;
        }
        
        public long getMinTime() {
            return minTime == Long.MAX_VALUE ? 0 : minTime;
        }
        
        public long getMaxTime() {
            return maxTime == Long.MIN_VALUE ? 0 : maxTime;
        }
    }
}